iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
AI & Data

Notion遇上LLM:30天打造我的AI知識管理系統系列 第 22

【Day 22】打造 RAG 智慧檢索系統:讓 Notion 筆記回答問題

  • 分享至 

  • xImage
  •  

為了打造 Notion Rag 系統,在前 21 天,我們做了許多「資料流」的工作:

  1. 從 Notion 撈資料(Database → Page → Block)
  2. 清理並寫入 SQLite / ChromaDB
  3. 使用 Notion AI 生成筆記
  4. 用 n8n 自動化收集資訊並寫入 Notion

現在,是時候讓這些資料真正能「被問、被用」了。今天我們將從後端開始,建立一個最小可行的 RAG 系統:用戶輸入問題 → 系統檢索相關筆記 → 生成智慧回答。

1. 什麼是 RAG ?

RAG (Retrieval-Augmented Generation) = 檢索增強生成,是一種結合「資訊檢索」和「語言生成」的 AI 技術。那麼,為什麼需要 RAG 呢?
在 LLM 的世界裡,模型的能力取決於「它知道什麼」。 而LLM 的三大問題:

  1. 知識有限:只知道訓練時的資料(例如 GPT-4 的知識截止於 2023 年)
  2. 容易幻覺:會編造不存在的資訊
  3. 無法客製化:不知道你的私人資料(公司文件、個人筆記)

因此,我們用 RAG 來「補足模型的記憶」:給 LLM 提供「參考資料」,讓它根據資料回答!

1.1 RAG 的運作流程

1. 用戶提問
   ↓
2. 從知識庫檢索相關資料(Retrieval)
   ↓
3. 把檢索到的資料 + 問題一起給 LLM
   ↓
4. LLM 根據資料生成回答(Generation)

1.2 具體例子

  • 沒有 RAG:
用戶:我們公司 Q3 營收多少?
AI:抱歉,我不知道你們公司的內部資料
  • 有 RAG:
用戶:我們公司 Q3 營收多少?
      ↓
系統:[從公司文件庫檢索] → 找到「Q3 財報.pdf」
      ↓
AI:根據 Q3 財報,營收為 500 萬美元,
    較 Q2 成長 15%

2. 系統流程設計

今天的目標是實作一個最小可行版本(MVP),串接前面完成的 Embedding 和 ChromaDB。

📝 用戶提問
    ↓
🔢 問題向量化(Embedding)
    ↓
🔍 ChromaDB 檢索(Top 3 相關筆記)
    ↓
📋 組合 Prompt(檢索內容 + 問題)
    ↓
🤖 LLM 生成回答
    ↓
💬 返回結果給用戶

3. 實作 RAG Backend

3.1 程式碼 notion_rag_backend.py

import os
import chromadb
from openai import OpenAI
from dotenv import load_dotenv

# 1. 載入環境變數
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# 2. 初始化 Chroma Client
chroma_client = chromadb.PersistentClient(path="db/chroma_db")
collection = chroma_client.get_or_create_collection("notion_notes")

# 3. 定義檢索函式
def retrieve_context(query, top_k=3):
    # 將 query 轉換為 embedding
    embedding = client.embeddings.create(
        model="text-embedding-3-small",
        input=query
    ).data[0].embedding

    # 從 ChromaDB 檢索最相關的 chunks
    results = collection.query(
        query_embeddings=[embedding],
        n_results=top_k
    )

    docs = results["documents"][0]
    metadatas = results["metadatas"][0]
    return list(zip(docs, metadatas))

# 4. 組合 prompt 並請求 LLM
def generate_answer(query):
    context_pairs = retrieve_context(query)
    context_text = "\n\n".join([f"- {doc}" for doc, _ in context_pairs])

    prompt = f"""
你是一位資料助理,請根據以下內容回答問題,若無相關資訊請說「資料庫中尚無此內容」:
---
{context_text}
---
問題:{query}
請以繁體中文回答,保留英文專有名詞。
"""

    completion = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant for knowledge retrieval."},
            {"role": "user", "content": prompt}
        ]
    )
    return completion.choices[0].message.content

# 5. 主程式入口
if __name__ == "__main__":
    query = input("請輸入你的問題:")
    answer = generate_answer(query)
    print("\n🔍 回答:\n", answer)

3.2 技術要點

  1. 初始化 Chroma 向量資料庫
chroma_client = chromadb.PersistentClient(path="db/chroma_db")
collection = chroma_client.get_or_create_collection("notion_notes")
  • 使用 PersistentClient 連接到本地 Chroma 資料夾(確保與 Day 16 相同路徑)。
  • get_or_create_collection():若 notion_notes 已存在則載入,否則新建。
  • Chroma Collection 相當於「向量索引庫」,內含:
    • documents:筆記內容的文字片段(chunk)
    • embeddings:每段文字的向量表示
    • metadatas:頁面、分類、來源資訊等
  1. 檢索函式 retrieve_context()
  • 把使用者輸入的問題轉成 embedding 向量。
  • 向 Chroma 查詢最相似的 top_k 筆文件。
  • 回傳文件與 metadata 的組合:
    return list(zip(docs, metadatas))
    
  • 模型選擇:
    • text-embedding-3-small → 成本低、速度快,適合個人筆記系統。
    • 若需更高準確率,可改用 text-embedding-3-large
  1. 回答生成函式 generate_answer()
  • 取出檢索到的內容,組合成 context_text。
  • 將 context 與問題整合成一個完整 prompt,交給 LLM 回答。
  • 使用 gpt-4o-mini 模型進行生成(性價比高)。
  • Prompt 內加入防呆機制:若無相關內容,請回答「資料庫中尚無此內容」
  • 提示模板(Prompt Template)
    你是一位資料助理,請根據以下內容回答問題,
    若無相關資訊請說「資料庫中尚無此內容」:
    ---
    {context_text}
    ---
    問題:{query}
    請以繁體中文回答,保留英文專有名詞。
    
    這樣可讓 LLM 生成時有明確上下文,減少「幻覺性回答」。
  1. 主程式入口
if __name__ == "__main__":
    query = input("請輸入你的問題:")
    answer = generate_answer(query)
    print("\n🔍 回答:\n", answer)

  • CLI 模式執行,可直接在終端互動。
  • 適合本地測試 RAG 系統,後續可改為:
    • Flask / FastAPI API endpoint
    • Streamlit 前端互動頁面

4. 實測結果

假設我問:

Q:AI 的發展有什麼關鍵訊號?

輸出可能像這樣:

🔍 回答:
根據數創電子報的內容,AI 模型的長任務處理能力與真實工作表現正在加速進步。
主要訊號包括:
1️⃣ 模型可連續執行任務的時間每 7 個月翻倍。
2️⃣ AI 開始參與模型研發,形成自我強化的回饋迴路。
3️⃣ 人類角色正從執行轉向監督與策展。

這樣,我的「Notion 筆記」終於能夠像資料助手一樣被提問、被引用。

5. 小結與下篇預告

今天我們完成了第一個可運作的 RAG pipeline:
核心流程:問題 → 檢索 → 回答
這代表著從「靜態儲存」進化到「主動應用」—— Notion 筆記不再只是沉默的記錄本,而是能對話、能回應的智能知識助手。

下一步,我們將用 Streamlit 打造一個互動式前端介面。從 CLI 到視覺化,從技術原型到實用工具。


上一篇
【Day 21】用 n8n 實作多來源電子報整合:Gmail × OpenAI × Notion:打造多線並行的 AI 知識中樞
下一篇
【Day 23】概念篇 - 用 Streamlit 打造 RAG 前端
系列文
Notion遇上LLM:30天打造我的AI知識管理系統23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言